﻿using System;
using System.Collections.Generic;

namespace ZCConsole.CI
{
    class PackToCI
    {
        public Pack CIPacket = new Pack();
        //string[] Station = new string[] { "108", "109", "202", "205", "305", "314", "407", "410" };
        HandleCIData CI;
        private ZC zc;

        public PackToCI(DeviceID SenderID, HandleCIData CI, ZC zc)
        {
            this.CI = CI;
            this.zc = zc;

            WriteCIHead(SenderID);

            SetLogicState(CI.InSections, CI.InRailSwitchs);
            CIPacket.Skip();

            SetLogicStopInfo(CI.InSections, CI.InRailSwitchs);
            CIPacket.Skip();

            SetSectionARB(CI.InSections, CI.InRailSwitchs);
            CIPacket.Skip();

            SetTrainAccessInfo();
            CIPacket.Skip();

            SetPSDReq();
            CIPacket.Skip();

            SetDataLength();
        }

        private void SetPSDReq()
        {
            //foreach (var psd in CI.InPSDoors)
            //{
            //    CIPacket.SetBit((psd as PSDoor).ShouldOpen);
            //}
        }

        private void SetSectionARB(List<Device> Sections, List<Device> Switchs)
        {
            foreach (var item in Sections)
            {
                if (item is Section)
                {
                    CIPacket.SetBit(false);
                }
            }

            List<string> railswitchs = new List<string>();

            foreach (var item in Switchs)
            {
                if (item is RailSwitch)
                {
                    RailSwitch railswitch = item as RailSwitch;
                    if (!railswitchs.Contains(railswitch.section.Name))
                    {
                        CIPacket.SetBit(false);
                        railswitchs.Add(railswitch.section.Name);
                    }
                }
            }
        }

        private void SetLogicStopInfo(List<Device> Sections, List<Device> Switchs)
        {
            foreach (var item in Sections)
            {
                if (item is Section)
                {
                    if ((item as Section).LogicCount == 1)
                    {
                        CIPacket.SetBit(false);
                    }
                    else
                    {
                        CIPacket.SetBit(false);
                        CIPacket.SetBit(false);
                    }
                }
            }
            List<string> railswitchs = new List<string>();
            foreach (var item in Switchs)
            {
                if (item is RailSwitch)
                {
                    RailSwitch railswitch = item as RailSwitch;
                    if (!railswitchs.Contains(railswitch.section.Name))
                    {
                        CIPacket.SetBit(false);
                        railswitchs.Add(railswitch.section.Name);
                    }
                }
            }
        }

        private void SetDataLength()
        {
            ushort Length = (ushort)CIPacket.byteFlag_;
            CIPacket.byteFlag_ = 6;
            CIPacket.PackUint16(Length);
            CIPacket.byteFlag_ = Length;
        }

        public void WriteCIHead(DeviceID SenderID)
        {
            PacketHeader head = new PacketHeader();
            CIPacket.PackUint16(0);
            CIPacket.PackUint16((UInt16)DataType.ZCToCI);
            CIPacket.PackByte((byte)DeviceID.ZC);
            CIPacket.PackByte((byte)SenderID);
            CIPacket.PackUint16(0);
        }

        private void SetTrainAccessInfo()
        {
            bool isNoncomTrain = false;
            foreach (Signal signal in CI.InSignals)
            {
                isNoncomTrain = false;
                List<Route> relatedRoutes = zc.data.Routes.FindAll((Route route) =>
                {
                    if (route.Start == signal)
                    {
                        return true;
                    }
                    return false;
                });
                foreach (Route route in relatedRoutes)
                {
                    if (route.Incoming[0] is Section)
                    {
                        if ((route.Incoming[0] as Section).HasNonComTrain.Count > 0)
                        {
                            isNoncomTrain = true;
                        }
                    }
                    else if (route.Incoming[0] is RailSwitch)
                    {
                        if ((route.Incoming[0] as RailSwitch).HasNonComTrain.Count > 0)
                        {
                            isNoncomTrain = true;
                        }
                    }
                }
                CIPacket.SetBit(isNoncomTrain ? false : true);
            }
        }

        public void SetLogicState(List<Device> Sections, List<Device> Switchs)
        {
            foreach (var item in Sections)
            {
                if (item is Section)
                {
                    if ((item as Section).LogicCount == 1)
                    {
                        bool bitFront = (item as Section).IsFrontLogicOccupy.Count == 0 ? false : true;
                        CIPacket.SetBit(!bitFront);
                    }
                    else
                    {
                        bool bitFront = (item as Section).IsFrontLogicOccupy.Count == 0 ? false : true;
                        CIPacket.SetBit(!bitFront);
                        bool bitLast = (item as Section).IsLastLogicOccupy.Count == 0 ? false : true;
                        CIPacket.SetBit(!bitLast);
                    }
                }
            }
            List<string> railswitchs = new List<string>();
            foreach (var item in Switchs)
            {
                if (item is RailSwitch)
                {
                    RailSwitch railswitch = item as RailSwitch;
                    if (!railswitchs.Contains(railswitch.section.Name))
                    {
                        bool bit = (item as RailSwitch).TrainOccupy.Count != 0 ? false : true;
                        CIPacket.SetBit(bit);
                        railswitchs.Add(railswitch.section.Name);
                    }
                }
            }
        }
    }
}
